﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "EditFamilyInProjectProcessEventHandler.h"
#include "EditFamilySharedContent.h"
#include "ComponentEditProjectState.h"

#include "FamilyUtils.h"
#include "GmCommunicationProtocolUtils.h"
#include "GmProcessServer.h"

// 平台头文件
#include "DebugMessage.h"
#include "StringUtil.h"
#include "TransferOwnership.h"
#include "IMainWindow.h"
#include "IUiDocument.h"
#include "IUiDocumentViewManager.h"
#include "CommandParameters.h"
#include "IDocument.h"
#include "IUiView.h"
#include "IFamilyConfigElement.h"
#include "IFamilyLoadOptions.h"
#include "FilePath.h"
#include "UiCommonDialog.h"
#include "DocumentPathUtils.h"

#include "IModelView.h"
#include "FamilyLoadOptionsWithUI.h"
#include "IUserTransaction.h"
#include "ICanvas.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

namespace
{
    bool GetFamilyLoadStrategy(IDocument * pDoc, const std::wstring & filePathName, FamilyFoundStrategy * pStrategy)
    {
        DBG_WARN_AND_RETURN_UNLESS(pDoc, false, L"pDoc为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_UNLESS(pStrategy, false, L"输出参数Strategy指针为空",L"GDMPLab",L"2024-03-30");

        std::wstring realFilePathName = filePathName;
        FilePath familyFilePath(realFilePathName);
        const IFamilyConfigElement* pFamilyConfigElement = IFamilyConfigElement::GetFamilyConfigElementByName(pDoc, familyFilePath.GetFileNameWithoutExtension());
        if (pFamilyConfigElement)
        {
            UiCommonDialog::ButtonType rt = UiCommonDialog::ShowMessageBox(GBMP_TR(L"载入构件"), GBMP_TR(L"构件已被载入，是否覆盖？"),
                (int)UiCommonDialog::ButtonType::Yes | (int)UiCommonDialog::ButtonType::No | (int)UiCommonDialog::ButtonType::Cancel);

            if (rt == UiCommonDialog::ButtonType::Cancel)
            {
                return false;
            }

            if (pStrategy)
            {
                *pStrategy = (rt == UiCommonDialog::ButtonType::Yes) ? gcmp::FamilyFoundStrategy::FF_Overwrite : gcmp::FamilyFoundStrategy::FF_Create;
            }
        }

        return true;
    }

    void LoadFamilyToMainDoc(const EditFamilySharedContent * pContent)
    {
        IMainWindow* pUIMainWnd = IMainWindow::GetMainWindow();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUIMainWnd, L"MainWnd为空",L"GDMPLab",L"2024-03-30");
        pUIMainWnd->ActivateWindow();
        IUiDocumentViewManager *pDocViewManager = IUiDocumentViewManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDocViewManager, L"pDocViewManager为空",L"GDMPLab",L"2024-03-30");
        IUiDocument *pUiDocument = pDocViewManager->GetCurrentUiDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocument, L"pUiDocument为空",L"GDMPLab",L"2024-03-30");
        gcmp::IDocument* pCurDocument = pUiDocument->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurDocument != nullptr, L"没有当前文档",L"GDMPLab",L"2024-03-30");
        if (DocumentPathUtils::GetTempDirectoryPath(pCurDocument) != pContent->GetMainDocumentPath())
        {
            std::vector<IUiDocument*> allUIDocs = pDocViewManager->GetAllUiDocuments();
            DBG_WARN_AND_RETURN_VOID_UNLESS(!allUIDocs.empty(), L"GBMP没有打开文档",L"GDMPLab",L"2024-03-30");

            FOR_EACH(pUiDoc, allUIDocs)
            {
                IDocument *pDocument = pUiDoc->GetDbDocument();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pDocument != nullptr, L"pDocument为空",L"GDMPLab",L"2024-03-30");
                if (DocumentPathUtils::GetTempDirectoryPath(pDocument) == pContent->GetMainDocumentPath())
                {
                    pCurDocument = pDocument;
                    pDocViewManager->ActivateUiDocument(pUiDoc->GetId(), -1);
                    std::vector<IModelView*> vecViews = IModelView::GetAllModelViews(pDocument);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(!vecViews.empty(), L"Document内没有ModelView",L"GDMPLab",L"2024-03-30");

                    pDocViewManager->ActivateUiView(pDocument->GetName(), StringUtil::ToWString((int)vecViews.front()->GetViewType()), vecViews.front()->GetName(), L"", true);
                }
            }

        }


        gcmp::FamilyFoundStrategy strategy = gcmp::FamilyFoundStrategy::FF_Create;
        if (!GetFamilyLoadStrategy(pCurDocument, pContent->GetEditFamilyFilePath(), &strategy))
        {
            return;
        }

        // 加载族文件
        std::wstring errorMsg;
        OwnerPtr<IUserTransaction> opLoadFamilyUt = IUserTransaction::Create(pCurDocument, GBMP_TR(L"加载构件"), true);
        DBG_WARN_AND_RETURN_VOID_UNLESS(opLoadFamilyUt, L"opLoadFamilyUt为空",L"GDMPLab",L"2024-03-30");

        FamilyLoadOptionsWithUI familyLoadOptionsImpl(strategy);
        if (!gcmp::FamilyUtils::LoadFamily(pCurDocument, pContent->GetEditFamilyFilePath(), errorMsg, &familyLoadOptionsImpl))
        {
            if (!errorMsg.empty())
            {
                UiCommonDialog::ShowMessageBox(GBMP_TR(L"打开文件"), errorMsg, (int)UiCommonDialog::ButtonType::OK);
            }
            return;
        }
        opLoadFamilyUt->Commit();

        IUiView* pUiView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiView, L"pUiView为空",L"GDMPLab",L"2024-03-30");
        ICanvas *pCanvas = pUiView->GetCanvas();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCanvas != nullptr, L"ICanvas指针无效",L"GDMPLab",L"2024-03-30");
        pCanvas->Refresh();
    }

}
gcmp::EditFamilyInProjectProcessEventHandler::~EditFamilyInProjectProcessEventHandler()
{
}

gcmp::EditFamilyInProjectProcessEventHandler::EditFamilyInProjectProcessEventHandler()
{
}

void gcmp::EditFamilyInProjectProcessEventHandler::On(OperationType operationType, OwnerPtr<NdbObject> opContent)
{
    switch (operationType)
    {
    case gcmp::OperationType::EndEdit:
        OnEndEdit(TransferOwnership(opContent));
        break;
    //case gcmp::OperationType::StartEdit:
    //    OnStartEdit(TransferOwnership(opContent));
    //    break;
    case gcmp::OperationType::RequestDocumentData:
        OnRequestProjectDocument(TransferOwnership(opContent));
        break;
    //case gcmp::OperationType::PostDocumentData:
    //    OnPostProjectDocumentData(TransferOwnership(opContent));
    //    break;
    case gcmp::OperationType::Ready:
        OnReady(TransferOwnership(opContent));
        break;
    default:
        DBG_WARN(L"未识别类型：" + StringUtil::ToWString((int)operationType),L"GDMPLab",L"2024-03-30");
        break;
    }
}

void EditFamilyInProjectProcessEventHandler::OnEndEdit(OwnerPtr<NdbObject> opContent)
{
    EditFamilySharedContent* pContent = quick_cast<EditFamilySharedContent>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent != nullptr, L"pContent为空",L"GDMPLab",L"2024-03-30");

    LoadFamilyToMainDoc(pContent);
    return;
}

void gcmp::EditFamilyInProjectProcessEventHandler::OnRequestProjectDocument(OwnerPtr<NdbObject> opContent)
{
    OwnerPtr<LoadFamilyToProjectSharedContent> opLoadSharedContent = TransferOwnershipCast<LoadFamilyToProjectSharedContent>(opContent);
    DBG_WARN_AND_RETURN_VOID_UNLESS(opLoadSharedContent, L"pUiView为空",L"GDMPLab",L"2024-03-30");
    std::vector<IUiDocument*> allUIDocs = IUiDocumentViewManager::Get()->GetAllUiDocuments();

    FOR_EACH(pUiDoc, allUIDocs)
    {
        IDocument *pDocument = pUiDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDocument != nullptr, L"pDocument为空",L"GDMPLab",L"2024-03-30");
        opLoadSharedContent->AddMainDocumentPathToNameMap(DocumentPathUtils::GetTempDirectoryPath(pDocument), DocumentPathUtils::GetProjectFileName(pDocument));
        opLoadSharedContent->SetMainServiceGuid(GuidUtils::ToString(ProcessServer::GetInstance()->GetServerGuid()));
    }

    CommunicationProtocolUtils::SendIpcMessage(opLoadSharedContent->GetRequestPort(), FunctionType::EditFamily, OperationType::PostDocumentData, opLoadSharedContent.get());
}

void gcmp::EditFamilyInProjectProcessEventHandler::OnReady(OwnerPtr<NdbObject> opContent)
{
    RpcServerInfo *pContent = quick_cast<RpcServerInfo>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent, L"pContent为空",L"GDMPLab",L"2024-03-30");

    CommunicationProtocolUtils::SendIpcMessage(pContent->GetPort(), FunctionType::EditFamily, OperationType::StartEditByCopy
        , ComponentEditProjectState::Get()->GetEditFamilySharedContent());
}

IUiDocument* gcmp::EditFamilyInProjectProcessEventHandler::GetCurrentUiDocument()
{
    IUiDocumentViewManager* pUiDocManager = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocManager, L"pUiDocManager为空",L"GDMPLab",L"2024-03-30");

    IUiDocument* pUiDoc = pUiDocManager->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    return pUiDoc;
}

IDocument* gcmp::EditFamilyInProjectProcessEventHandler::GetCurrentDocument()
{
    IUiDocument* pUiDoc = GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    return pUiDoc->GetDbDocument();
}
